//
//  Funtions.m
//  MailDelivery
//
//  Created by Dante Palacios on 26/08/09.
//  Copyright 2009 Dante Palacios. All rights reserved.
//

#import <WebKit/WebKit.h>
#import <QTKit/QTKit.h>

#import "Message.h"
#import "Keychain.h"
#import "KeychainItem.h"

#import "NSAttributedStringAdditions.h"
#import "NSDictionaryAdditions.h"
#import "NSDataAdditions.h"
#import "NSStringAdditions.h"

#import "Funtions.h"
#import "Macros.h"


NSString *KeychainGetPasswordForAccount(NSDictionary *account) 
{
	return [[[Keychain sharedKeychain] keychainItemForAccount:account] password];
}

BOOL KeychainSetPasswordForAccount(NSString *password, NSDictionary *account) 
{
	KeychainItem *item = [[Keychain sharedKeychain] addKeychainItemForAccount:account];
	if (item) 
	{
		[item setPassword:password];
		return YES;
	}
	return NO;
}

BOOL IsImageFile(NSString *path) 
{
	NSArray *types = [NSImage imageFileTypes];
	for (NSString *type in types)
	{
		if ([type isCaseInsensitiveEqualToString:[path pathExtension]]) return YES;
	}
	
	return NO;
}

BOOL IsMovieFile(NSString *path) {
	NSWorkspace *sharedWorkspace = [NSWorkspace sharedWorkspace];
	NSString *type = [sharedWorkspace typeOfFile:path error:nil];
	if (type) 
	{
		if ([sharedWorkspace type:type conformsToType:@"public.movie"]) return YES;
	}
	
	if (IsAudioFile(path)) return NO;
	
	NSArray *types = [QTMovie movieFileTypes:QTIncludeCommonTypes];
	for (type in types) 
	{
		if ([type isCaseInsensitiveEqualToString:[path pathExtension]]) return YES;
	}
	
	return NO;
}

BOOL IsAudioFile(NSString *path) 
{
	NSWorkspace *sharedWorkspace = [NSWorkspace sharedWorkspace];
	NSString *type = [sharedWorkspace typeOfFile:path error:nil];
	if (type) 
	{
		return [sharedWorkspace type:type conformsToType:@"public.audio"];
	}
	
	return NO;
}

BOOL IsValidEmail(NSString *emailAddress) 
{
	if (!emailAddress.length) return NO;
	
	NSString *emailRegEx =
    @"(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
    @"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
    @"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
    @"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
    @"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
    @"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
    @"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";
	
	return [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegEx] evaluateWithObject:emailAddress];
	
}

BOOL IsMobileMeHost(NSString *hostName) 
{
	return !hostName.length ? NO : ([hostName isCaseInsensitiveEqualToString:@"smtp.mac.com"] || [hostName isCaseInsensitiveEqualToString:@"smtp.me.com"]);
}

CFNetDiagnosticStatus MailDeliveryValidateConnectionWithURL(NSURL *url, NSString **diagnosticDescription) 
{
	CFStringRef description = nil;
	CFNetDiagnosticRef diagnostic = CFNetDiagnosticCreateWithURL(NULL, (CFURLRef)url);
	CFNetDiagnosticStatus status = CFNetDiagnosticCopyNetworkStatusPassively(diagnostic, &description);        
	CFRelease(diagnostic);
	
	if (diagnosticDescription) 
	{
		*diagnosticDescription = (NSString *)description;
	}
	
	if (description) 
	{
		CFRelease(description);
	}
	return status;
}

CFNetDiagnosticStatus MailDeliveryValidateInternetConnection(NSString **diagnosticDescription) {
	return MailDeliveryValidateConnectionWithURL([NSURL URLWithString:@"https://code.google.com/p/maildelivery/"], diagnosticDescription);
}

NSString *HumanReadableFileSizeUsingFormat(NSNumber *fileSize, NSString *format) {
	unsigned long long sizeInBytes = [fileSize unsignedLongLongValue];
	CGFloat finalValue = 0;
	NSString *suffix = @"";
	
	if (!format.length) 
	{
		format = @"#,###.##;0.00;(#,##0.00)";
	}
	
	if (sizeInBytes < 1024) 
	{
		suffix = MDLocalizedString(@"bytes", @"");
		finalValue = (CGFloat)sizeInBytes;
	}
	else if (sizeInBytes < 1024 * 1024) 
	{
		suffix = MDLocalizedString(@"KB", @"");
		finalValue = ((CGFloat)sizeInBytes/1024.0);
	}
	else if (sizeInBytes < 1024 * 1024 * 1024) 
	{
		suffix = MDLocalizedString(@"MB", @"");
		finalValue = ((CGFloat)sizeInBytes/1024.0/1024.0);
	}
	else 
	{
		suffix = MDLocalizedString(@"GB", @"");
		finalValue = ((CGFloat)sizeInBytes/1024.0/1024.0/1024.0);
	}
	
	NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
	[formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
	[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
	[formatter setDecimalSeparator:@","];
	[formatter setFormat:format];
	
	NSString *humanReadableSize = [formatter stringFromNumber:[NSNumber numberWithDouble:finalValue]];
	[formatter release];
	
	return [NSString stringWithFormat:@"%@ %@", humanReadableSize, suffix];
}

OSStatus GetCertificateRefForEmail(NSString *email, SecKeychainItemRef *itemRef) 
{
	NSCParameterAssert(email);
	
	SecKeychainAttributeList attrList;
    SecKeychainAttribute attrib;
    attrList.count = 1;
    attrList.attr  = &attrib;
    attrib.tag = kSecAlias;
    attrib.data = (void *) [email UTF8String];
    attrib.length = (UInt32)strlen(attrib.data);
	
    SecKeychainSearchRef searchRef = nil;
	
    OSStatus status = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, &attrList, &searchRef);
	if (status != noErr) 
	{
		NSLog(@"GetCertificateRefForEmail err* %s", GetMacOSStatusErrorString(status));
		return status;
	}
	
    status = SecKeychainSearchCopyNext(searchRef, itemRef);
    if (searchRef) CFRelease(searchRef);
	
    return status;
}

NSString *MIMETypeOfFile(NSString *filename) 
{
	NSString *extension = filename.pathExtension;
	if (!extension.length) return nil;
	
	CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL);
	if (!UTI) return nil;
	
	NSString *mimeType = nil;
	CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
	if (!registeredType) 
	{
		if ([extension isEqualToString:@"m4v"]) 
            mimeType = @"video/x-m4v";
        else if([extension isEqualToString:@"m4p"])
            mimeType = @"audio/x-m4p";
        else if ([extension isEqualToString:@"p7m"]) 
            mimeType = @"application/pkcs7-mime";
        else
			mimeType = @"application/octet-stream";
	}
	else 
    {
		mimeType = NSMakeCollectable(registeredType);
	}
	
	CFRelease(UTI);
	return mimeType;
}

void MailDeliveryLog(NSString *format, ...)
{
    
}

BOOL MailContentsOfURL(NSURL *URL, NSString **errorDescription) 
{
	NSCParameterAssert(URL);
	/*CFURLRef mailerURLRef;
	NSURL * mailtoURL = [NSURL URLWithString:@"mailto:xxx"];
	OSStatus err = LSGetApplicationForURL((CFURLRef)mailtoURL, kLSRolesAll, NULL, &mailerURLRef);
	if (err != noErr) 
	{
		if (errorDescription) *errorDescription = [NSString stringWithFormat:@"%s", GetMacOSStatusErrorString(err)];
		return NO;
	}
	
	NSString *mailerPath = [(NSURL*)mailerURLRef path];
	CFRelease(mailerURLRef);
	
	NSBundle *bundle = [NSBundle bundleWithPath:mailerPath];*/
    NSBundle *bundle = [NSBundle bundleWithPath:[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"com.apple.mail"]];
	if (!bundle) 
	{
		if (errorDescription) *errorDescription = MDLocalizedString(@"Bundle for mailer not found", @"error description");
		return NO;
	}
	
	NSDictionary *infoPlist = [bundle infoDictionary];
	NSNumber *mailPageSupported = [infoPlist objectForKey:@"MailPageSupported"];
	if (!mailPageSupported || ![mailPageSupported boolValue]) 
	{
		if (errorDescription) *errorDescription = [NSString stringWithFormat:MDLocalizedString(@"\"%@\" does not support sending Web pages", @"error description format"), [bundle objectForInfoDictionaryKey:(NSString *) kCFBundleNameKey]];
		return NO;
	}
	
	NSString *bundleId = [bundle bundleIdentifier];
	const char *bundleIdChar = [bundleId UTF8String];
	if (!bundleIdChar) 
	{
		if (errorDescription) *errorDescription = @"";
		return NO;
	}
	
	if (![[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:bundleId options:NSWorkspaceLaunchAsync additionalEventParamDescriptor:nil launchIdentifier:NULL]) 
	{
		if (errorDescription) *errorDescription = [NSString stringWithFormat:MDLocalizedString(@"Failed to launch application \"%@\"", @"error description format"), bundleId];
		return NO;
	}
	
	WebView *webView = [[WebView alloc] initWithFrame:NSZeroRect];
	[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:URL]];
	
	while ([webView isLoading]) 
	{
		CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
	}
	
	WebArchive *webArchive = [[[webView mainFrame] dataSource] webArchive];
	NSString *subject = [[[webView mainFrame] dataSource] pageTitle];
	
	[webView release];
	
    if (!webArchive) 
	{
		if (errorDescription) *errorDescription = @"";
        return NO;
    }
	
	NSAppleEventDescriptor *dataDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:'tdta' data:webArchive.data];
	NSAppleEventDescriptor *subjectDesc = [NSAppleEventDescriptor descriptorWithString:subject];
	NSAppleEventDescriptor *targetDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeApplicationBundleID bytes:bundleIdChar length:strlen(bundleIdChar)];
	
	NSAppleEventDescriptor *appleEvent = [NSAppleEventDescriptor appleEventWithEventClass:'mail' eventID:'mlpg' targetDescriptor:targetDesc returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID];
	
	[appleEvent setParamDescriptor:dataDesc forKeyword:keyDirectObject];
	[appleEvent setParamDescriptor:subjectDesc forKeyword:'urln'];
	
	OSStatus err = AESendMessage([appleEvent aeDesc], NULL, kAECanInteract, kAEDefaultTimeout);
	if (err != noErr) 
	{
		if (errorDescription) *errorDescription = [NSString stringWithFormat:@"%s", GetMacOSStatusErrorString(err)];
		return NO;
	}
	
	return YES;
}

BOOL MailLinkToURL(NSURL *URL, NSString **errorDescription) 
{
	NSCParameterAssert(URL);
	NSString *title = @"Page title";
    NSString *subject = [NSString stringWithFormat:@"SUBJECT=%@", [title stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    
    NSString *body = [NSString stringWithFormat:@"BODY=%@", [[NSString stringWithFormat:@"\n\n<%@>", [URL absoluteString]] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
    
	return [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?%@&%@", @"", subject, body]]];
}
